import {
  inject,
  InjectionKey,
  provide,
  reactive,
  watch,
  computed,
  ComputedRef,
  ref,
  Ref,
  nextTick,
  onMounted,
  onBeforeUnmount,
} from 'vue';
import { useHttp } from './useHttp';
import { calculateX, calculateY } from './useConvertMap';
import { clamp, isFunction } from '@lagabu/tool';
import { useRoute } from 'vue-router';
const SH_COORDS = [121.47, 31];
export const CheckboxSymbol: InjectionKey<{
  state: {
    shaActive: boolean;
    pvgActive: boolean;
    airbusActive: boolean;
    cargoActive: boolean;
  };
  mapState: {
    rawArray: Array<any>;
    currentArray: Array<any>;
    currentNation: string;
    currentScale: number;
    currentMid: Array<number>;
    minX: number;
    maxX: number;
    minY: number;
    maxY: number;
  };
  getFlightLines: (...args: any) => any;
  filterCurrentArray: (...args: any) => any;
  register: (...args: any) => any;
  unregister: (...args: any) => any;
  computedAirport: ComputedRef<'' | 'SHA' | 'PVG' | undefined>;
  mapRef: Ref<null | HTMLElement>;
}> = Symbol('Checkbox');

export function useCheckboxProvider() {
  const state = reactive({
    shaActive: true,
    pvgActive: true,
    airbusActive: true,
    cargoActive: true,
  });
  const $route = useRoute();
  const { get } = useHttp();
  const mapRef = ref<null | HTMLElement>(null);
  const mapState = reactive({
    rawArray: [],
    currentArray: [] as any[],
    currentNation: '',
    currentScale: 1,
    currentMid: [180, 180],
    minX: SH_COORDS[0],
    maxX: SH_COORDS[0],
    minY: SH_COORDS[1],
    maxY: SH_COORDS[1],
  });
  const callbacks = new Map();
  let timerId: any = 0,
    timerInterval = 1000 * 60 * 10;
  watch(
    [
      () => state.shaActive,
      () => state.pvgActive,
      () => state.airbusActive,
      () => state.cargoActive,
    ],
    (newVal, oldVal) => {
      if (newVal.length !== oldVal.length) return;
      let n: boolean,
        o: boolean,
        flag = false;
      for (let i = 0; i < newVal.length; i++) {
        n = newVal[i];
        o = oldVal[i];
        if (n !== o) {
          flag = true;
          break;
        }
      }
      if (!flag) return;
      mapState.currentArray = filterCurrentArray(mapState.rawArray);
      if (mapState.currentArray.length !== 0) moveMap();
      // if (newVal[0] === oldVal[0] && newVal[1] === oldVal[1]) return;
      updateCallbacks();
    }
  );

  function updateCallbacks() {
    for (let entry of callbacks.entries()) {
      if (isFunction(entry[0])) entry[0].apply(null, entry[1]);
    }
  }

  onMounted(() => {
    timerId = setInterval(() => {
      updateCallbacks();
      getFlightLines();
    }, timerInterval);
  });

  onBeforeUnmount(() => {
    clearInterval(timerId);
    timerId = 0;
  });

  const computedAirport = computed(() => {
    if ($route.fullPath.match(/(pvg)/i)) return 'PVG';
    if (state.shaActive && state.pvgActive) return '';
    else if (state.shaActive) return 'SHA';
    else if (state.pvgActive) return 'PVG';
    else return;
  });

  /**
   * 注册更新函数以联动checkbox
   * @param cb
   * @param params
   */
  function register(cb: (...args: any[]) => any, ...params: any[]) {
    callbacks.set(cb, params);
  }

  function unregister(cb: (...args: any[]) => any) {
    callbacks.delete(cb);
  }

  function resetMinMax() {
    mapState.minX = SH_COORDS[0];
    mapState.maxX = SH_COORDS[0];
    mapState.minY = SH_COORDS[1];
    mapState.maxY = SH_COORDS[1];
  }

  function getFlightLines(continental = '', nation = '', airport = '') {
    return get('/getFlightLines', {
      continental: continental,
      nation: nation,
      airport: computedAirport.value,
    })
      .then((result) => {
        if (result && result.status && result.status === 200) {
          const resultArr = result.data;
          mapState.rawArray = resultArr;
          mapState.currentArray = filterCurrentArray(resultArr);

          if (mapState.currentArray.length !== 0) moveMap();
        }
      })
      .catch((err) => {
        console.error(err);
      });
  }
  function moveMap() {
    nextTick(() => {
      if (mapRef.value) {
        translateAndScaleMap((mapRef.value as any).svg);
      }
    });
  }
  function translateAndScaleMap(elem: SVGGElement) {
    let edge = Math.max(
      mapState.maxX - mapState.minX + 20,
      mapState.maxY - mapState.minY + 20
    );
    mapState.currentMid = [
      calculateX((mapState.maxX + mapState.minX) / 2),
      calculateY((mapState.maxY + mapState.minY) / 2),
    ];
    mapState.currentScale = 360 / edge;
    if (mapState.currentScale === Infinity) {
      mapState.currentScale = 1;
      return;
    }
    // elem.setAttribute(
    //   'transform-origin',
    //   `${mapState.currentMid[0]} ${mapState.currentMid[1]}`
    // );
    // elem.setAttribute(
    //   'transform',
    //   `translate(${(mapState.currentMid[0] - 180) * -1} ${
    //     (mapState.currentMid[1] - 180) * -1
    //   }) scale(${mapState.currentScale})`
    // );
  }

  function calculateMinMax(coords: number[]) {
    mapState.minX = Math.min(coords[0], mapState.minX);
    mapState.maxX = Math.max(coords[0], mapState.maxX);
    mapState.minY = Math.min(coords[1], mapState.minY);
    mapState.maxY = Math.max(coords[1], mapState.maxY);
  }

  function filterCurrentArray(arr: Array<any>) {
    // 重置地图上的最值点
    resetMinMax();

    // 根据底部的多选按钮对数据进行筛选
    let objMap: Map<string, any> = new Map(),
      tempObj: string = '';
    for (let elem of arr) {
      let portCertificated = false,
        typeCertificated = false;
      if ((state.shaActive && !elem.pvg) || (state.pvgActive && elem.pvg)) {
        portCertificated = true;
      }

      if (
        (state.airbusActive && elem.airbus) ||
        (state.cargoActive && !elem.airbus)
      ) {
        typeCertificated = true;
      }

      if (portCertificated && typeCertificated) {
        tempObj = JSON.stringify({
          airbus: elem.airbus,
          pvg: elem.pvg,
          coordinates: elem.coordinates,
          portName: elem.portName,
          continental: elem.continental,
        });

        calculateMinMax(elem.coordinates);

        if (!objMap.has(tempObj)) {
          objMap.set(tempObj, {
            entryExit: elem.exit ? 1 : 0,
          });
        } else {
          let val = objMap.get(tempObj),
            tempExitValue = elem.exit ? 1 : 0;
          val.entryExit = val.entryExit !== tempExitValue ? 2 : tempExitValue;
        }
      }
    }
    let resultArr = [];
    for (let entry of objMap.entries()) {
      resultArr.push({
        ...JSON.parse(entry[0]),
        ...entry[1],
      });
    }

    return resultArr;
  }
  provide(CheckboxSymbol, {
    state,
    mapState,
    getFlightLines,
    filterCurrentArray,
    register,
    unregister,
    computedAirport,
    mapRef,
  });

  return {
    state,
  };
}

export function useCheckboxInjector() {
  return inject(CheckboxSymbol, {
    state: {
      shaActive: false,
      pvgActive: false,
      airbusActive: false,
      cargoActive: false,
    },
    mapState: {
      rawArray: [],
      currentArray: [],
      currentNation: '',
      currentScale: 1,
      currentMid: [180, 180],
      minX: SH_COORDS[0],
      maxX: SH_COORDS[0],
      minY: SH_COORDS[1],
      maxY: SH_COORDS[1],
    },
    getFlightLines: function () {},
    filterCurrentArray: function () {},
    register: function () {},
    unregister: function () {},
    computedAirport: computed(() => undefined),
    mapRef: ref(null),
  });
}
